在 [Day 16] 自制 Laravel helper response function 提到自製的 SystemResponse,在這邊 Resource Collections 結合 SystemResponse,如下:
<?php
Route::get('product', function(){
    
    // 一頁顯示 4 筆資料
    $pageProduct = Product::paginate(4);
    return SystemResponse::dataResponse(ProductCollection::make($pageProduct));
}
{
    "timestamp": "2023",
    "status": 200,
    "message": "查詢成功",
    "data": [
        {
            "id": 1,
            "customer_id": 1,
            "product_number": "230626000001"
        },
        {
            "id": 2,
            "customer_id": 1,
            "product_number": "230626000002"
        },
        {
            "id": 3,
            "customer_id": 1,
            "product_number": "230626000003"
        },
        {
            "id": 4,
            "customer_id": 3,
            "product_number": "230626000004"
        }
    ]
}
從輸出結果來看,ProductCollection::make($pageProduct) 透過 SystemResponse 後,只有保留 ProductResource 在 public function toArray($request) 的內容。 像是 meta, link..等分頁資訊,都直接被濾掉!
此時要將 Meta Data 顯示在 Eloquent’s resource collection 內,必須設法將 meta, link 資訊加在 class ProductCollection 的 public function toArray($request) -參考 Laravel Adding Meta Data
追追看 class ProductCollection 的 $this->resource 會是什麼,如:
<?php
class ProductCollection extends ResourceCollection
{
    public function toArray($request)
    {
        $resource = $this->resource;
        dd($resource); // Illuminate\Pagination\LengthAwarePaginator
    }
}

顯然是 Laravel 管理分頁呈現方式的 class,繼續往 class LengthAwarePaginator 的挖,發現 public function toArray() 的部分內容很是面熟:

很像上篇文章的 『多筆資料 - 分頁輸出 Eloquent’s resource collection make() + paginate()』結果的 meta, link..等分頁資訊
meta, link..等分頁資訊:"links": {
        "first": "http://127.0.0.1:8001/v1/product?page=1",
        "last": "http://127.0.0.1:8001/v1/product?page=2",
        "prev": null,
        "next": "http://127.0.0.1:8001/v1/product?page=2"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 2,
        "links": [
            {..略},
        ],
        "path": "http://127.0.0.1:8001/v1/product",
        "per_page": 4,
        "to": 4,
        "total": 8
    }
依照 class LengthAwarePaginator 的 public function toArray() 部分內容加入至 class ProductCollection 的 public function toArray(),如:
<?php
class ProductCollection extends ResourceCollection
{
    public function toArray($request)
    {
        $resource = $this->resource;
        return [
            'list'          => $this->collection,
            'totalPages'    => $resource->lastPage(),
            'currentPage'   => $resource->currentPage(),
            'count'         => $resource->total()
        ];
    }
}
{
    "timestamp": "2023",
    "status": 200,
    "message": "查詢成功",
    "data": {
        "list": [
            {
                "id": 1,
                "customer_id": 1,
                "product_number": "230626000001"
            },
            {
                "id": 2,
                "customer_id": 1,
                "product_number": "230626000002"
            },
            {
                "id": 3,
                "customer_id": 1,
                "product_number": "230626000003"
            },
            {
                "id": 4,
                "customer_id": 3,
                "product_number": "230626000004"
            }
        ],
        "totalPages": 2,
        "currentPage": 1,
        "count": 8
    }
}
遇到情況需要自制 Collection Resource 時, class ModelCollection 就會派上用場,如果僅僅只是需要分頁效果,其實 class ModelResource 只要善用 paginate() 或是 collection() 就可以做到分頁的效果。
除了上述 Adding Meta Data (public function toArray()) 的方法外,Laravel 還有提供其他的分頁方法-參考 Laravel Paginator / LengthAwarePaginator Instance Methods
1 [Day 16] 自制 Laravel helper response function
2 Laravel Adding Meta Data
3 Laravel Paginator / LengthAwarePaginator Instance Methods